﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;

namespace Pavilion
{
    internal class PolygonAndMultiLineIntersection
    {
        internal MultiLineCollisionData MultiLineCollisionData { get; private set; }
        internal PolygonCollisionData PolygonCollisionData { get; private set; }
        private PolygonPhysicalData PolygonData { get { return MultiLineCollisionData.PhysicalData as PolygonPhysicalData; } }
        private MultiLinePhysicalData MultiLineData { get { return PolygonCollisionData.PhysicalData as MultiLinePhysicalData; } }
        private bool checkIntersection;

        private List<PolygonPhysicalData> changedPolygons;
        private List<MultiLinePhysicalData> changedMultiLines;

        public PolygonAndMultiLineIntersection(MultiLineCollisionData multiLineCollisionData, PolygonCollisionData polygonCollisionData)
        {
            this.checkIntersection = true;
            this.MultiLineCollisionData = multiLineCollisionData;
            this.PolygonCollisionData = polygonCollisionData;

            changedPolygons = new List<PolygonPhysicalData>();
            changedMultiLines = new List<MultiLinePhysicalData>();

            //PolygonData.PhysicalFormChanged += (p) => changedPolygons.Add(p as PolygonPhysicalData);
            //MultiLineData.PhysicalFormChanged += (m) => changedMultiLines.Add(m as MultiLinePhysicalData);
            PolygonData.PhysicalFormChanged += new Action<PhysicalData>(PhysicalData_PhysicalFormChanged);
            MultiLineData.PhysicalFormChanged += new Action<PhysicalData>(PhysicalData_PhysicalFormChanged);
            PolygonData.PositionChanged += new Action<PhysicalData>(PhysicalData_PositionChanged);
            MultiLineData.PositionChanged += new Action<PhysicalData>(PhysicalData_PositionChanged);

            multiLineCollisionData.Disposed += CollisionData_Disposed;
            polygonCollisionData.Disposed += CollisionData_Disposed;
        }

        internal void UpdateIntersection()
        {
            if (!checkIntersection)
                return;

            checkIntersection = false;
            bool intersected = false;

            foreach (LineVector line in MultiLineData.LineCollection)
            {
                if (LineVector.Intersects(PolygonData.PhysicalBounds, line))
                {
                    MultiLineCollisionData.AddLine(MultiLineData, line);
                    intersected = true;
                }
                else
                {
                    MultiLineCollisionData.RemoveLine(MultiLineData, line);
                }
            }

            if (intersected)
                PolygonCollisionData.AddPolygon(PolygonData);
            else
                PolygonCollisionData.RemovePolygon(PolygonData);
        }

        private void PhysicalData_PhysicalFormChanged(PhysicalData physicalData) { checkIntersection = true; }

        private void PhysicalData_PositionChanged(PhysicalData physicalData) { checkIntersection = true; }

        //Need to refactor this. Not good for performance.
        private void CollisionData_Disposed()
        {
            if (PolygonCollisionData == null)
                return;

            PolygonCollisionData.RemovePolygon(PolygonData);

            foreach (LineVector line in MultiLineData.LineCollection)
                MultiLineCollisionData.RemoveLine(MultiLineData, line);

            PolygonCollisionData = null;
            MultiLineCollisionData = null;
        }
    }
}
